


function randomMime(game) {
    let mines = [];
    let existed = {};

    for (let i = 0; i < game.numofMines; i++) {
        while (true) {
            let rowIdx = Math.floor(Math.random() * game.nRows);
            let colIdx = Math.floor(Math.random() * game.nCols);
            let key = `${rowIdx},${colIdx}`;

            if (key in existed) {
                continue;
            }

            mines.push([rowIdx, colIdx]);
            existed[key] = true;
            break;
        }
    }

    game.mines = mines;
}



function handleClick(game, rowIdx, colIdx) {
    if (game.state === 0) {
        startingGame(game);
    }

    if (game.state === 2 || game.state === 3) {
        return;
    }

    let { nRows, nCols, cells } = game;

    console.log(nRows, nCols);

    let cell = cells[rowIdx][colIdx];

    if (cell.flag) {
        cell.flag = false;
        cell.el.classList.remove("flag");
        return;
    }

    if (cell.value == -1) {
        cell.el.classList.add("exploded");
        loseGame(game);

    } else if (cell.value > 0) {
        openCell(cell);
    } else if (cell.value == 0) {
        clearsafearea(game, rowIdx, colIdx);
    }

    checkWin(game);

    //console.log(cell);
}

function openCell(cell) {
    cell.open = true;
    cell.el.classList.add("open");
}

function winGame(game) {
    game.state = 2;
    clearInterval(game.intervalId);
    let el = document.querySelector(".game-info > .status");
    el.innerText = "WIN!!!";
    openAllCelss(game);
}

function loseGame(game) {
    game.state = 3;

    clearInterval(game.intervalId);

    let el = document.querySelector(".game-info > .status");
    el.innerText = "LOSE";
    openAllCelss(game);
}

function openAllCelss(game) {
    let { cells, nRows, nCols } = game;
    for (let rowIdx = 0; rowIdx < nRows; rowIdx++) {
        for (let colIdx = 0; colIdx < nCols; colIdx++) {
            let cell = cells[rowIdx][colIdx];
            if (!cell.open) {
                openCell(cell)
            }
        }
    }

}

function startingGame(game) {
    game.state = 1;

    game.intervalId = setInterval(() => {
        game.elapsed = game.elapsed + 1;
        refreshTimer(game);
    }, 1000);
}

function showRemainNum(game) {
    let remainingDiv = document.querySelector(".game-info > .remaining");
    remainingDiv.innerText = game.remainingNum;
}

function refreshTimer(game) {
    let el = document.querySelector(".game-info > .timer");
    el.innerText = game.elapsed;
}


function handleFlagCell(game, rowIdx, colIdx) {
    let { nRows, nCols, cells } = game;

    if (game.state === 0) {
        startingGame(game);
    }

    if (game.state === 2 || game.state === 3) {
        return;
    }

    let cell = cells[rowIdx][colIdx];
    if (cell.open) {
        return;
    }

    if (cell.flag) {
        cell.flag = false;
        cell.el.classList.remove("flag");
        game.remainingNum = game.remainingNum + 1;
        showRemainNum(game);
    } else {
        if (game.remainingNum > 0) {
            cell.flag = true;
            cell.el.classList.add("flag");
            game.remainingNum = game.remainingNum - 1;
            showRemainNum(game);
        }
    }

    checkWin(game);
}

function handlenumber(game, rowIdx, colIdx) {
    let { nRows, nCols, cells } = game;
    let cell = cells[rowIdx][colIdx];
    for (let [deltaRow, deltaCol] of directions) {
        let newRow = rowIdx + deltaRow;
        let newCol = colIdx + deltaCol;
        if (newRow < 0 || newRow >= nRows) {
            continue;
        }
        if (newCol < 0 || newCol >= nCols) {
            continue;
        }
        let neighborCell = cells[newRow][newCol];
        if (neighborCell.open || neighborCell.flag) {
            continue;
        }
        if (neighborCell.value >= 0) {
            neighborCell.open = true;
            neighborCell.el.classList.add("open");
            continue;
        }
        if (neighborCell.value == -1) {
            neighborCell.open = true;
            neighborCell.el.classList.add("exploded");
            loseGame(game);
        }
    }
}


function checkWin(game) {
    let { cells, nRows, nCols } = game;
    let clearNum = 0;
    let untouchedNum = 0;
    for (let rowIdx = 0; rowIdx < nRows; rowIdx++) {
        for (let colIdx = 0; colIdx < nCols; colIdx++) {
            let cell = cells[rowIdx][colIdx];
            if (cell.flag && cell.value === -1) {
                clearNum = clearNum + 1;
            }

            if (!cell.open) {
                untouchedNum = untouchedNum + 1;
            }
        }
    }

    if (clearNum === game.numofMines || untouchedNum === game.numofMines) {
        winGame(game);
        return;
    }
}

function clearsafearea(game, rowIdx, colIdx) {
    let { nRows, nCols, cells } = game;
    let cell = cells[rowIdx][colIdx];
    if (cell.value != 0) {
        return;
    }
    cell.open = true
    cell.el.classList.add("open");

    for (let [deltaRow, deltaCol] of directions) {
        let newRow = rowIdx + deltaRow;
        let newCol = colIdx + deltaCol;
        if (newRow < 0 || newRow >= nRows) {
            continue;
        }
        if (newCol < 0 || newCol >= nCols) {
            continue;
        }

        console.log("clear:", newRow, newCol, nCols);


        let neighborCell = cells[newRow][newCol];

        if (neighborCell.open || neighborCell.flag) {
            continue;
        }

        if (neighborCell.value > 0) {
            neighborCell.open = true
            neighborCell.el.classList.add("open");
            continue;
        }

        if (neighborCell.value == 0) {
            clearsafearea(game, newRow, newCol);
        }

    }
}


function countSurroundingMines(game) {
    let { nRows, nCols, cells } = game;

    for (let rowIdx = 0; rowIdx < nRows; rowIdx++) {
        for (let colIdx = 0; colIdx < nCols; colIdx++) {
            let cell = cells[rowIdx][colIdx];

            if (cell.value == -1) {
                continue;
            }

            let numMines = 0;

            for (let [deltaRow, deltaCol] of directions) {
                let newRow = rowIdx + deltaRow;
                let newCol = colIdx + deltaCol;

                if (newRow < 0 || newRow >= nRows || newCol < 0 || newCol >= nCols) {
                    continue;
                }

                let neighborCell = cells[newRow][newCol];

                if (neighborCell.value == -1) {
                    numMines++;
                }
            }

            cell.value = numMines;

            if (numMines == 1) {
                cell.el.classList.add('warn-1');
            } else if (numMines == 2) {
                cell.el.classList.add("warn-2");
            } else if (numMines == 3) {
                cell.el.classList.add("warn-3");
            } else if (numMines == 4){
                cell.el.classList.add("warn-4");
            } else if (numMines == 5){
                cell.el.classList.add("warn-5");
            } else if (numMines == 6){
                cell.el.classList.add("warn-6");
            } else if (numMines == 7){
                cell.el.classList.add("warn-7");
            } else if (numMines == 8){
                cell.el.classList.add("warn-8");
            } 

            if (numMines > 0) {
                let mineEl = cell.el.querySelector(".mine");
                mineEl.innerText = numMines;
            }
        }
    }
}

function startGame(difficulty) {
    // 重置失败状态
    let statusEl = document.querySelector(".game-info > .status");
    statusEl.innerText = ""; // 清空状态显示

    let game = {
        elapsed: 0,
        state: 0, // 0:ready; 1:running, 2:win; 3:lose
        drawGrid: function() {
            let tblEl = document.querySelector("#gameboard > table.mime-gird");
            tblEl.innerHTML = ""; 

            let cells = [];
            for (let rowIdx = 0; rowIdx < this.nRows; rowIdx++) {
                let trEl = document.createElement("tr");
                let cellRow = [];
                for (let colIdx = 0; colIdx < this.nCols; colIdx++) {
                    let tdEl = document.createElement("td");

                    let cellDiv = document.createElement("div");
                    cellDiv.className = "cell";

                    cellDiv.innerHTML = `<div class="mine"></div><div class="flag">&#128681;</div>`;

                    cellDiv.addEventListener("click", (e) => {
                        handleClick(game, rowIdx, colIdx);
                    });

                    cellDiv.addEventListener("contextmenu", (e) => {
                        e.preventDefault();
                        handleFlagCell(game, rowIdx, colIdx);
                    });

                    cellDiv.addEventListener("dblclick", (e) => {
                        handlenumber(game, rowIdx, colIdx);
                    });

                    tdEl.append(cellDiv);
                    trEl.append(tdEl);

                    cellRow.push({
                        open: false,
                        el: cellDiv,
                        value: 0, 
                        flag: false
                    });
                }

                cells.push(cellRow);
                tblEl.append(trEl);
            }

            this.cells = cells;

            // 绘制地雷
            for (let mine of this.mines) {
                let [rowIdx, colIdx] = mine;
                let cell = cells[rowIdx][colIdx];
                cell.value = -1; // 有雷设置-1，没有雷此值表示周边雷数
                let mineEl = cell.el.querySelector(".mine");
                mineEl.innerHTML = "&#128163"; 
            }

            showRemainNum(game);
            refreshTimer(game);
        }
    };

    switch (difficulty) {
        case 'easy':
            game.nRows = 9;
            game.nCols = 9;
            game.numofMines = 10;
            break;
        case 'medium':
            game.nRows = 16;
            game.nCols = 16;
            game.numofMines = 40;
            break;
        case 'hard':
            game.nRows = 16;
            game.nCols = 30;
            game.numofMines = 99;
            break;
        default:
            game.nRows = 9;
            game.nCols = 9;
            game.numofMines = 10;
            break;
    }

    game.remainingNum = game.numofMines;

    randomMime(game);
    game.drawGrid();
    countSurroundingMines(game); 
}


function main() {
    console.log("main")
    startGame("easy");

}


let directions = [
    [-1, -1], ///左上
    [-1, 0], ///中上
    [-1, 1], ///右上
    [0, -1], ///左
    [0, 1], ///右
    [1, -1], ///左下
    [1, 0], ///中下
    [1, 1], ///右下
]

let mock_mines = [
    [
        1,
        5
    ],
    [
        1,
        7
    ],
    [
        5,
        2
    ],
    [
        0,
        2
    ],
    [
        8,
        3
    ],
    [
        2,
        1
    ],
    [
        2,
        3
    ],
    [
        0,
        8
    ],
    [
        8,
        5
    ],
    [
        0,
        4
    ]
]

